﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media.Effects;
using System.Windows.Threading;
using WindowsPhoneToolbox.Util;
using Microsoft.Expression.Media.Effects;
using Microsoft.SmartDevice.Connectivity;
using AppRes = WindowsPhoneToolbox.Resources;

namespace WindowsPhoneToolbox.Controls
{
    /// <summary>
    /// Interaction logic for ConnectDeviceControl.xaml
    /// </summary>
    public partial class ConnectDeviceControl : INotifyPropertyChanged
    {
        private readonly Device _defaultDevice;
        private readonly DispatcherTimer _timer;

        private static bool IsInDesignModeStatic
        {
            get
            {
                return
                    (bool)
                    DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)).Metadata.DefaultValue;
            }
        }

        public ConnectDeviceControl()
        {
            InitializeComponent();
            CboDevices.SelectedIndex = -1;
            UiDisconnected();
            if (!IsInDesignModeStatic)
            {
                _defaultDevice = WPhoneDevice.DefaultDevice();
                CboDevices.ItemsSource = WPhoneDevice.ListDevices();
                CboDevices.SelectedItem = _defaultDevice;
            }
            else
            {
                PhoneManufature = "Phone Manufature";
                PhoneVersion = "Phone Version";
            }
            _timer = new DispatcherTimer {Interval = TimeSpan.FromMilliseconds(1000)};
            _timer.Tick += TimerTick;
        }

        public static readonly RoutedEvent ActionEvent =
                EventManager.RegisterRoutedEvent("ConnectCommand", RoutingStrategy.Bubble,
                typeof(RoutedEventHandler), typeof(ConnectDeviceControl));

        public event RoutedEventHandler ConnectCommand
        {
            add { AddHandler(ActionEvent, value); }
            remove { RemoveHandler(ActionEvent, value); }
        }
        
        private void TimerTick(object sender, EventArgs e)
        {
            if (!WPhoneDevice.ValidateConnected() && IsConnected)
            {
                Status = AppRes.WaitDisconnecting;
                Bntconnect.IsEnabled = false;
                BntDisconnect.IsEnabled = false;
                CboDevices.IsEnabled = false;
                Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(TryDisconnectCallBack));
                _timer.Stop();
            }
        }

        private Device _seletectDevice;
        public Device SeletectDevice
        {
            get { return _seletectDevice; }
            private set
            {
                _seletectDevice = value;
                NotifyPropertyChanged("SeletectDevice");
            }
        }

        private string _status;
        public string Status
        {
            get { return _status; }
            private set
            {
                if (_status != value)
                {
                    _status = value;
                    NotifyPropertyChanged("Status");
                }
            }
        }

        private bool _isConnected;
        public bool IsConnected
        {
            get { return _isConnected; }
            private set
            {
                if (_isConnected != value)
                {
                    _isConnected = value;
                    NotifyPropertyChanged("IsConnected");
                    NotifyPropertyChanged("MenuEfect");
                    NotifyPropertyChanged("MenuEfectEmulator");
                }
            }
        }

        public Effect MenuEfect
        {
            get
            {
                if (IsConnected)
                {
                    return null;
                }
                var effect = new BloomEffect { BloomSaturation = 0.01, BaseIntensity = 0.16, BloomIntensity = 0.45 };
                return effect;
            }
        }

        private string _phoneManufature;
        public string PhoneManufature
        {
            get { return _phoneManufature; }
            private set
            {
                if (_phoneManufature != value)
                {
                    _phoneManufature = value;
                    NotifyPropertyChanged("PhoneManufature");
                }
            }
        }

        private string _phoneVersion;
        public string PhoneVersion
        {
            get { return _phoneVersion; }
            private set
            {
                if (_phoneVersion != value)
                {
                    _phoneVersion = value;
                    NotifyPropertyChanged("PhoneVersion");
                }
            }
        }

        public void TargetConnect(string targetDevice)
        {
            MsgErro.Text = string.Empty;
            MsgErro.Visibility = Visibility.Collapsed;
            Status = AppRes.WaitTtryConnecting;
            Bntconnect.IsEnabled = false;
            CboDevices.IsEnabled = false;
            var args = new List<object> { targetDevice };
            Dispatcher.BeginInvoke(DispatcherPriority.Background, new TargetConnectCommandHandle(TargetConnectCallBack), args.ToArray());
        }

        private delegate void TargetConnectCommandHandle(object[] args);

        private void TargetConnectCallBack(object[] args)
        {
            var targetDevice = (string)args[0];
            
            if (WPhoneDevice.IsConnected)
            {
                WPhoneDevice.Disconnect();
                IsConnected = false;
            }
            var errors = string.Empty;
            foreach (var dev in WPhoneDevice.AvaliableDevices.Where(dev => dev.Name == targetDevice))
            {
                CboDevices.SelectedItem = dev;
                if (WPhoneDevice.Connect(dev))
                {
                    SeletectDevice = WPhoneDevice.CurrentDevice;
                    LoadDeviceInfo();
                    BntDisconnect.IsEnabled = true;
                    DeviceInfo.IsEnabled = true;
                    DeviceInfo.IsExpanded = true;
                    Status = Common.GetStatus();
                    IsConnected = true;
                    _timer.Start();
                }
                else
                {
                    if (!string.IsNullOrEmpty(WPhoneDevice.Error))
                    {
                        errors += dev.Name + " : " + WPhoneDevice.Error + "; ";
                    }
                }
                break;
            }
            if (!WPhoneDevice.IsConnected)
            {
                UiDisconnected();
                MsgErro.Text = errors;
                MsgErro.Visibility = Visibility.Visible;
            }
            else
            {
                CboDevices.SelectedItem = WPhoneDevice.CurrentDevice;
                var temp = ActionEvent;
                if (temp != null)
                {
                    var arg = new ConnectPhoneEvent(true) { RoutedEvent = temp };
                    RaiseEvent(arg);
                }
            }
        }

        private void UiDisconnected()
        {
            SeletectDevice = null;
            CboDevices.IsEnabled = true;
            Bntconnect.IsEnabled = true;
            BntDisconnect.IsEnabled = false;
            MsgErro.Text = string.Empty;
            MsgErro.Visibility = Visibility.Collapsed;
            DeviceInfo.IsExpanded = false;
            DeviceInfo.IsEnabled = false;
            PhoneManufature = string.Empty;
            PhoneVersion = string.Empty;
            Status = Common.GetStatus();
            IsConnected = false;
        }

        private void TryDisconnectCallBack()
        {
            WPhoneDevice.Disconnect();
            UiDisconnected();
            var temp = ActionEvent;
            if (temp != null)
            {
                var arg = new ConnectPhoneEvent(false) { RoutedEvent = temp };
                RaiseEvent(arg);
            }
        }

        private void TryconnectCallBack()
        {
            if (WPhoneDevice.Connect((Device)CboDevices.SelectedItem))
            {
                SeletectDevice = WPhoneDevice.CurrentDevice;
                LoadDeviceInfo();
                DeviceInfo.IsEnabled = true;
                DeviceInfo.IsExpanded = true;
                Status = Common.GetStatus();
                IsConnected = true;
                BntDisconnect.IsEnabled = true;
                _timer.Start();
                var temp = ActionEvent;
                if (temp != null)
                {
                    var arg = new ConnectPhoneEvent(true) { RoutedEvent = temp }; 
                    RaiseEvent(arg);
                }
            }
            else
            {
                UiDisconnected();
                MsgErro.Text = WPhoneDevice.Error;
                MsgErro.Visibility = Visibility.Visible;
            }
        }

        private void BntconnectClick(object sender, RoutedEventArgs e)
        {
            MsgErro.Text = string.Empty;
            MsgErro.Visibility = Visibility.Collapsed;
            Status = AppRes.WaitConnecting;
            Bntconnect.IsEnabled = false;
            CboDevices.IsEnabled = false;
            Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(TryconnectCallBack));
        }

        private void LoadDeviceInfo()
        {
            DevInfoPlataform.Text = WPhoneDevice.CurrentDevice.Platform.Name;
            DevInfoBuild.Text = WPhoneDevice.SystemInfo.OSBuildNo.ToString(CultureInfo.InvariantCulture);
            DevInfoVersion.Text = new Version(WPhoneDevice.SystemInfo.OSMajor, WPhoneDevice.SystemInfo.OSMinor).ToString();
            DevInfoAchiteture.Text = WPhoneDevice.SystemInfo.ProcessorArchitecture + " " +
                                     WPhoneDevice.SystemInfo.InstructionSet + " " +
                                     WPhoneDevice.SystemInfo.NumberOfProcessors.ToString(CultureInfo.InvariantCulture) + 
                                     AppRes.Processor;
            DevInfoAvalMemory.Text = WPhoneDevice.SystemInfo.AvailPhys.ToString(CultureInfo.InvariantCulture);
            DevInfoTotMemory.Text = WPhoneDevice.SystemInfo.TotalPhys.ToString(CultureInfo.InvariantCulture);

            PhoneManufature = WPhoneDevice.CurrentDevice.Name;
            PhoneVersion = DevInfoVersion.Text;

        }

        private void BntDisconnectClick(object sender, RoutedEventArgs e)
        {
            Status = AppRes.WaitDisconnecting;
            Bntconnect.IsEnabled = false;
            BntDisconnect.IsEnabled = false;
            CboDevices.IsEnabled = false;
            Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(TryDisconnectCallBack));
        }

        # region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        #endregion

    }
}
